<?php
namespace App\Service\OrderService\OrderNotifyService;

use Hyperf\Task\Annotation\Task;
use App\Service\Code\Normal;
use App\Model\PssModel\OrderStoreBond;
use Service\AppService\IdService;
use App\Model\CommodityModel\SupplierCommodity;
use App\Model\PssModel\OrderStoreBondGoods;
use App\Model\PssModel\OrderStoreBondBindUser;
use App\Model\PssModel\Business;
use Hyperf\Utils\WaitGroup;
use App\Service\PushService\BusinessPushService;
use Hyperf\DbConnection\Db;
use App\Model\PssLogModel\InterfaceRequest;

class GwNotifyService extends BaseNotifyService
{
    protected $user_type    = 'shopgw';
    protected $message_type = 'OrderExpress';

    /**
     * @Task
     * 接收关务通知物流轨迹
     * @param array $param
     */
    public function orderTraceLogistics( $param = [] )
    {
        $rule = [
            "OrderStatus"       => '订单申报清关状态',
            "OrderNo"           => '渠道商订单号',
            "OrderCode"         => '关务订单号',
            "LogisticsName"     => '物流公司名称',
            "LogisticsNo"       => '物流公司运单号',
            "PayFlowNo"         => '支付流水号',
            "PayCompanyName"    => '支付公司',
            "InvtReleaseTime"   => '清关放行时间',
            "InvtCode"          => '清单放行单号',
            "Message"           => '清关结果',
        ];

        foreach ($rule as $key => $value ) {
            if( !array_key_exists($key,$param) ) {
                return Normal::returnCode(Normal::FAIL,"请求参数【{$key}】缺失");
            }
        }

        $response = $this->getResponseCode();
        $this->response_to_req = $response;
        $this->message = $param;
        $this->event_sn = $param['OrderNo'];
        $this->message_type = 'OrderExpress';
        $result = $this->addNotifyCallBackLog();
        if( $result['code'] != Normal::SUC ) {
            return $result;
        }
        return $response;
    }

    public function goodsReceive($param=[])
    {
        $rule = [
            "datas" => 'datas不能为空',
        ];

        foreach ($rule as $key => $value ) {
            if( !array_key_exists($key,$param) ) {
                return Normal::returnCode(Normal::FAIL,"请求参数【{$key}】缺失");
            }
        }
        $response = $this->getResponseCode();
        $this->response_to_req = $response;
        $this->message = $param;
        $firstGoods=current($param['datas']);
        $this->event_sn = $firstGoods['goodsSKU'];
        $this->message_type = 'GoodsReceive';
        $result = $this->addNotifyCallBackLog();
        if( $result['code'] != Normal::SUC ) {
            return $result;
        }
        return $response;

    }

    /**
     * 接收关务消息报文
     * @param array $param
     * @return mixed
     */
    public function MessageRev(array $param=[])
    {
        $rule = [
            "data"          => '消息数据',
            "MessageType"   => '消息类型',
        ];

        foreach ($rule as $key => $value ) {
            if( !array_key_exists($key,$param) ) {
                return Normal::returnCode(Normal::FAIL,"请求参数【{$key}】缺失");
            }
        }
        
        $response = $this->getResponseCode();
        $this->response_to_req = $response;
        $this->message = $param;
        
        $messageType    = $param['MessageType'];
        $data           = $param['data'];
        
        //保税入库单
        if( $messageType == 'BondedOrderGoodsStore' )
        {
            $data = $param['data'];
            $request_start_time = (string)microtime(true);
            //写入日志            
            $result = $this->addBondOrderData($data,$param['supplierID']);
            $request_used_time  = bcsub((string)microtime(true),(string)$request_start_time,3);
            //记录数据
            InterfaceRequest::instance()->addLog([
                'interface_code'    => $messageType,
                'bid'               => 0,
                'type'              => 1,
                'request_use_time'  => $request_used_time,
                'request_param'     => json_encode($param,JSON_UNESCAPED_UNICODE),
                'response_data'     => json_encode($result,JSON_UNESCAPED_UNICODE),
                'response_code'     => $result['code'],
                'response_msg'      => $result['msg'],
            ]);
            return $result;
        } else if( $messageType == 'GoodsReceive' ) {//商品接收
            $firstGoods         = current($data);
            $this->event_sn     = $firstGoods['goodsSKU'];
            $this->message_type = $messageType;
        } else { //同步订单轨迹
            $this->message      = $data;
            $this->event_sn     = $data['OrderNo'];
            $this->message_type = $messageType;
        }
        
        $result = $this->addNotifyCallBackLog();
        if( $result['code'] != Normal::SUC ) {
            return $result;
        }
        return $response;
    }

    /**
     * 写入云仓保税入库单数据
     * @param array $data
     * @param string $supplierID
     */
    public function addBondOrderData( array $data,$supplierID)
    {
        try
        {
            $orderNo            = (string)$data['ReturnOrderNumber'];
            $goodsList          = $data['returnOrderInfoCommodityLinks'];
            $supplierID         = (string)$supplierID;
            $returnedQuantity   = (string)$data['ReturnedQuantity'];
            if( empty($returnedQuantity) )  {
                return Normal::returnCode(Normal::FAIL,"推送保展出库单库存总数ReturnedQuantity不能为空，请联系云仓相关管理人员进行核查之后，再重新发起推送!");
            }
            
            //读取当前
            $hasOrder = OrderStoreBond::instance()->info([
                'order_sn'      => $orderNo,
                'company_id'    => $supplierID
            ]);
			
            if( ! empty($hasOrder) )  {
				return Normal::returnCode(Normal::SUC,"推送保展出库订单信息成功!");
            }
			
			//判断有没有配置渠道
			$bindUserList = OrderStoreBondBindUser::instance()->where('bid','>',0)->get()->toArray();
			if( empty($bindUserList) ) {
				return Normal::returnCode(Normal::FAIL,"云仓保税展示出库单渠道默认配置未进行配置，请联系云仓相关管理人员进行核查之后，再重新发起推送!");
			}
			
			//判断是否是自营bbc渠道
			$bids = array_column($bindUserList,'bid');
			$userList = Business::instance()->whereIn('id',$bids)->where('user_source','<>',2)->get()->toArray();
			if( !empty($userList) ) {
				return Normal::returnCode(Normal::FAIL,"云仓保税展示出库单渠道默认配置错误,存在非自营渠道的大B渠道用户bid，请联系云仓相关管理人员进行核查之后，再重新发起推送!");
			}
			
			//判断是否是自营bbc渠道
			$bids = array_column($bindUserList,'bid');
			$userList = Business::instance()->whereIn('id',$bids)->where('user_source','=',2)->where('is_channel',2)->get()->toArray();
			if( !empty($userList) ) {
				return Normal::returnCode(Normal::FAIL,"云仓保税展示出库单渠道默认配置错误,暂时不支持三方渠道，请联系云仓相关管理人员进行核查之后，再重新发起推送!");
			}
			
			$CommodityEbcNos = array_column($goodsList,'CommodityEbcNo');
			$CommodityEbcNosNew = array_filter($CommodityEbcNos);
			if( count($CommodityEbcNos) != count($CommodityEbcNosNew) ) {
				return Normal::returnCode(Normal::FAIL,"接收关务保展出库单商品明细里面存在CommodityEbcNo电商平台货号为空的数据，请联系关务相关管理人员进行核查之后，再重新发起推送!");
			}
							
			//查询供应商商品关联的自编码
			$CommodityEbcNos = array_unique($CommodityEbcNosNew);
			$supplierCommodityLists = SupplierCommodity::instance()
			->select([
				'SupplierCommoditySkuCode',
				'SKUCode'
			])
			->where('SupplierCompanyID',$supplierID)
			->whereIn('SupplierCommoditySkuCode',$CommodityEbcNos)
			->get()
			->toArray();
			
			$supplierCommodityListsMap = array_column($supplierCommodityLists,'SKUCode','SupplierCommoditySkuCode');                
			
			
			OrderStoreBond::instance()->startTrans();
			
			//写入主订单
			$_insert_bond_id = IdService::instance()->getOtherID();
			
			//写入商品明细
			$_insert_bond_goods = [];
			$BondedOrderGoodsStoreGoodsList = [];
			foreach ($goodsList as $item)
			{
				$CommodityEbcNo = $item['CommodityEbcNo'];
				if( !isset($supplierCommodityListsMap[$CommodityEbcNo]) ) {
					OrderStoreBond::instance()->rollback();
					return Normal::returnCode(Normal::FAIL,"接收关务保展出库单商品商平台货号【{$CommodityEbcNo}】未关联云仓主档案，请联系云仓相关管理人员进行核查之后，再重新发起推送!");
				}
				
				$period     = $item['ValidityPeriod'] ? date("Ymd",strtotime($item['ValidityPeriod'])) : '';
				$skucode    = $supplierCommodityListsMap[$CommodityEbcNo];
				$barcode    = $item['BarCode'];
				$goods_name = $item['CommodityName'];
				$number     = $item['ReturnedQuantity'];
				$price      = $item['Price'];
				
				if( empty($number) )  {
				    OrderStoreBond::instance()->rollback();
				    return Normal::returnCode(Normal::FAIL,"推送保展出库单对应电商平台货号{$CommodityEbcNo}，库存总数ReturnedQuantity不能为空，请联系云仓相关管理人员进行核查之后，再重新发起推送!");
				}
				
				$_insert_bond_goods[] = [
					'id'                        => IdService::instance()->getOtherID(),
					'order_bond_id'             => $_insert_bond_id,
					'skucode'                   => $skucode,
					'barcode'                   => $barcode,
					'supplier_skucode'          => $CommodityEbcNo,
					'supplier_commodity_name'   => $goods_name,
					'supplier_commodity_number' => $number,
					'supplier_commodity_period' => $period,
					'supplier_commodity_price'  => $price,
				];
				
				$BondedOrderGoodsStoreGoodsList[] = [
					'goodsName'         => (string)$goods_name,
					'barCode'           => (string)$barcode,
					'skuCode'           => (string)$skucode,
					'supplierSkuCode'   => (string)$CommodityEbcNo,
					'number'            => (string)$number,
					'period'            => (string)$period,
					'price'             => (string)$price
				];
			}

			//写入出库订单数据
			$_data = [
				'id'            => $_insert_bond_id,
				'order_sn'      => $orderNo,
				'company_id'    => $supplierID,
				'stock_num'     => $returnedQuantity,
				'cd'            => time(),
			];
			$_result = OrderStoreBond::instance()->insert($_data);
			if( !$_result ) {
				OrderStoreBond::instance()->rollback();
				return Normal::returnCode(Normal::FAIL,"云仓写入出库订单失败，请稍后再试，请回关务系统重新发起推送保展出库订单信息！");
			}
			
			//写入出库单商品明细
			$_result = OrderStoreBondGoods::instance()->insert($_insert_bond_goods);
			if( !$_result ) {
				OrderStoreBond::instance()->rollback();
				return Normal::returnCode(Normal::FAIL,"云仓写入出库订单商品流程失败，请回关务系统重新发起推送保展出库订单信息！");
			}
			
			//获取配置用户数据
			$body = [
				'orderNo'       => $orderNo,
				'number'        => $returnedQuantity,
				'supplierID'    => $supplierID,
				'goodsList'     => $BondedOrderGoodsStoreGoodsList
			];
			$userList = Business::instance()->select(["*",Db::raw("id as bid")])->whereIn('id',$bids)->get()->toArray();
			$result = [];
			$count = count($userList);
			$wg = new WaitGroup();
			$wg->add($count);
			foreach ($userList as $key => $binfo)
			{
				co(function () use ($wg,$key,$binfo,$body,& $result) 
				{
					$result[] = BusinessPushService::instance()->pushMessage('BondedOrderGoodsStore',$binfo,$body);
					$wg->done();
				});
			}
			
			$wg->wait();
			
			//处理推送结果
			foreach ($result as $item)
			{
				if( $item['code'] != Normal::SUC ) 
				{
					OrderStoreBond::instance()->rollback();
					return Normal::returnCode(Normal::FAIL,"云仓推送大B渠道接收入库订单数据失败【{$item['msg']}】,请回关务系统重新发起推送保展出库订单信息！");
				}
			}
			
			OrderStoreBond::instance()->commit();
			return Normal::returnCode(Normal::SUC,"推送保展出库订单信息成功!");			
        }
        catch ( \Throwable $th )
        {
            OrderStoreBond::instance()->rollback();
            return Normal::returnCode(Normal::FAIL,"发生异常【{$th->getMessage()},{$th->getFile()},{$th->getLine()}】");
        }
    }

    /**
     * 获取接收响应标准
     * 参照当前上游通知业务标准来
     */
    public function getResponseCode()
    {
        return Normal::returnCode(Normal::SUC,"接收成功");
    }
}